﻿using System.Collections.Generic;
using System.Text;

namespace Heb2RusEngine
{
    public class HebrewLetter
    {
        readonly List<char> niqqudList = new List<char>();
        public char Letter { get; private set; }
        public bool ContainsShva { get { return niqqudList.Contains(HebrewNiqqud.Shva); } }
        public bool ContainsKamatz { get { return niqqudList.Contains(HebrewNiqqud.Kamatz); } }
        public bool ContainsZeire { get { return niqqudList.Contains(HebrewNiqqud.Zeire); } }
        public bool ContainsKubutz { get { return niqqudList.Contains(HebrewNiqqud.Kubutz); } }
        public bool ContainsHolam { get { return niqqudList.Contains(HebrewNiqqud.Holam); } }
        public bool ContainsShuruk { get { return niqqudList.Contains(HebrewNiqqud.Shuruk); } }
        public bool ContainsHiriq { get { return niqqudList.Contains(HebrewNiqqud.Hiriq); } }
        public bool ContainsSegol { get { return niqqudList.Contains(HebrewNiqqud.Segol); } }
        public bool ContainsPatach { get { return niqqudList.Contains(HebrewNiqqud.Patach); } }
        public bool ContainsSinDot { get { return niqqudList.Contains(HebrewNiqqud.SinDot); } }
        public bool ContainsShinDot { get { return niqqudList.Contains(HebrewNiqqud.ShinDot); } }
        public bool ContainsHatavKamatz { get { return niqqudList.Contains(HebrewNiqqud.HatavKamatz); } }
        public bool ContainsHatavPatah { get { return niqqudList.Contains(HebrewNiqqud.HatavPatah); } }
        public bool ContainsHatavSegol { get { return niqqudList.Contains(HebrewNiqqud.HatavSegol); } }
        public bool ContainsDagesh { get { return niqqudList.Contains(HebrewNiqqud.Dagesh); } }
        public HebrewLetter(char letter)
        {
            Letter = letter;
        }
        public void AddNiqqud(char niqqud)
        {
            niqqudList.Add(niqqud);
        }
        public bool isHasNiqqud()
        {
            return niqqudList.Count > 0;
        }
        public bool isHasPureNiqqud()
        {
            bool dageshOnly = niqqudList.TrueForAll(s => s == HebrewNiqqud.Dagesh || s == HebrewNiqqud.ShinDot || s == HebrewNiqqud.SinDot);
            return niqqudList.Count > 0 && !dageshOnly;
        }
        public bool ContainsLowNiqqud()
        {
            return niqqudList.Exists(HebrewWord.isNiqqudLow);
        }
    }
    public class SimpleHebrewWord
    {
        public bool IsPrevActual { get { return HebrewLetterList.Count > 1; } }
        public int LetterIndexInWord { get { return HebrewLetterList.Count; } }
        public List<HebrewLetter> HebrewLetterList { get; private set; }
        public HebrewLetter PrevLetter { get { return HebrewLetterList[LetterIndexInWord - 2]; } }
        public HebrewLetter TheLetter { get { return HebrewLetterList[LetterIndexInWord - 1]; } }
        public SimpleHebrewWord()
        {
            HebrewLetterList = new List<HebrewLetter>();
            Clear();
        }
        public void Clear()
        {
            HebrewLetterList.Clear();
        }
        public void AddLetter(char hebrewLetter)
        {
            HebrewLetterList.Add(new HebrewLetter(hebrewLetter));
        }

        public void AddShva()
        {
            TheLetter.AddNiqqud(HebrewNiqqud.Shva);
        }
        public void AddKamatz()
        {
            TheLetter.AddNiqqud(HebrewNiqqud.Kamatz);
        }
        public void AddZeire()
        {
            TheLetter.AddNiqqud(HebrewNiqqud.Zeire);
        }
        public void AddHolam()
        {
            TheLetter.AddNiqqud(HebrewNiqqud.Holam);
        }
        public void AddShuruk()
        {
            TheLetter.AddNiqqud(HebrewNiqqud.Shuruk);
        }
        public void AddHiriq()
        {
            TheLetter.AddNiqqud(HebrewNiqqud.Hiriq);
        }
        public void AddSegol()
        {
            TheLetter.AddNiqqud(HebrewNiqqud.Segol);
        }
        public void AddPatach()
        {
            TheLetter.AddNiqqud(HebrewNiqqud.Patach);
        }
    }

    enum State { WORD, NOT_WORD };

    public enum Statement { START, NOT_START } ;
    public class Hebrew2RussianTranslit
    {
        public IStatement Statement = new NullStatementProcessing();

        public string ConvertLine(string hebrewString)
        {
            State state = State.NOT_WORD;

            StringBuilder result = new StringBuilder();
            StringBuilder currentWord = new StringBuilder();

            for (int i = 0; i < hebrewString.Length; i++)
            {
                char currentSymbol = hebrewString[i];
                bool hebrewSymbol = HebrewWord.isHebrewLetter(currentSymbol, true);
                bool point = currentSymbol == '.';

                //Statement.ProcessPoint(point);

                switch (state)
                {
                    case State.WORD:
                        if (hebrewSymbol)
                        {
                            currentWord.Append(currentSymbol);
                        }
                        else
                        {
                            state = State.NOT_WORD;
                            AddWordToResult(result, currentWord, Statement);
                            Statement.Statement = Heb2RusEngine.Statement.NOT_START;
                            Statement.ProcessPoint(point);
                            result.Append(currentSymbol);
                            currentWord = new StringBuilder();
                        }
                        break;
                    case State.NOT_WORD:
                        if (hebrewSymbol)
                        {
                            state = State.WORD;
                            currentWord = new StringBuilder().
                                Append(currentSymbol);
                        }
                        else
                        {
                            result.Append(currentSymbol);
                        }
                        break;
                }
            }

            if (currentWord.Length > 0)
            {
                AddWordToResult(result, currentWord, Statement);
            }

            return result.ToString();
        }
        public string ConvertWord(string hebrewWordText)
        {
            #region pre processing
            string translitValue;
            if (specialWords.TryGetValue(hebrewWordText, out translitValue))
                return translitValue;
            if (hebrewWordText.EndsWith(HebrewSpecial.NameOfG_d_With_Prefix_X))
            {
                string prefix = hebrewWordText.Substring(0, hebrewWordText.Length - HebrewSpecial.NameOfG_d_With_Prefix_X.Length);
                string prefixRussian = ConvertWord(prefix);
                if (prefixRussian.Length > 1 && prefixRussian.EndsWith("а"))
                    prefixRussian = prefixRussian.Remove(prefixRussian.Length - 1);
                return prefixRussian + Name_russian;
            }
            #endregion

            StringBuilder russianString = new StringBuilder();
            const string preFix = "     ";
            const string postFix = "     ";
            string line = preFix + hebrewWordText + postFix;

            HebrewWord hebrewWord = new HebrewWord(hebrewWordText);
            bool special_O_should_be_Added = false;

            for (int index = 0; index < hebrewWord.AsList.Count; index++)
            {
                HebrewLetter letter = hebrewWord.AsList[index];
                bool isFirstLetterInWord = (index == 0);
                bool isLastLetterInWord = (index == hebrewWord.AsList.Count - 1);
                bool isSecondFromEnfOfWord = (index == hebrewWord.AsList.Count - 2);

                HebrewLetter prevLetter = isFirstLetterInWord ? new HebrewLetter(' ') : hebrewWord.AsList[index - 1];
                HebrewLetter nextLetter = isLastLetterInWord ? new HebrewLetter(' ') : hebrewWord.AsList[index + 1];

                #region special cases
                if (isSecondFromEnfOfWord)
                {
                    if (letter.Letter == HebrewAlphabet.Yod &&
                        nextLetter.Letter == HebrewAlphabet.Vav &&
                        (prevLetter.ContainsKamatz || prevLetter.ContainsPatach))
                    {
                        russianString.Append(RussianAlphabet.Ve);
                        break;
                    }
                }
                #endregion

                switch (letter.Letter)
                {
                    #region Rule 2
                    case HebrewAlphabet.Bet:
                        russianString.Append(letter.ContainsShuruk ? RussianAlphabet.Be : RussianAlphabet.Ve);
                        break;
                    case HebrewAlphabet.Gimel:
                        russianString.Append(RussianAlphabet.Ge);
                        break;
                    case HebrewAlphabet.Dalet:
                        russianString.Append(RussianAlphabet.De);
                        break;
                    case HebrewAlphabet.Zayin:
                        russianString.Append(RussianAlphabet.Ze);
                        break;
                    case HebrewAlphabet.Het:
                        russianString.Append(RussianAlphabet.Xa);
                        break;
                    case HebrewAlphabet.Tet:
                        russianString.Append(RussianAlphabet.Te);
                        break;
                    case HebrewAlphabet.Kaf:
                    case HebrewAlphabet.FinalKaf:
                        russianString.Append(letter.ContainsShuruk ? RussianAlphabet.Ka : RussianAlphabet.Xa);
                        break;
                    case HebrewAlphabet.KafWithDagesh:
                        russianString.Append(RussianAlphabet.Ka);
                        break;
                    case HebrewAlphabet.Lamed:
                        russianString.Append(RussianAlphabet.L);
                        if (isLastLetterInWord && !letter.isHasNiqqud())
                            russianString.Append(RussianAlphabet.SoftSign);
                        break;
                    case HebrewAlphabet.Mem:
                    case HebrewAlphabet.FinalMem:
                        russianString.Append(RussianAlphabet.M);
                        break;
                    case HebrewAlphabet.Nun:
                    case HebrewAlphabet.FinalNun:
                        russianString.Append(RussianAlphabet.N);
                        break;
                    case HebrewAlphabet.Samekh:
                        russianString.Append(RussianAlphabet.Se);
                        break;
                    case HebrewAlphabet.Pe:
                    case HebrewAlphabet.FinalPe:
                        russianString.Append(isFirstLetterInWord || letter.ContainsShuruk ? RussianAlphabet.Pe : RussianAlphabet.Fe);
                        break;
                    case HebrewAlphabet.PeWithDagesh:
                        russianString.Append(RussianAlphabet.Pe);
                        break;
                    case HebrewAlphabet.Tsadi:
                    case HebrewAlphabet.FinalTsadi:
                        russianString.Append(RussianAlphabet.Tse);
                        break;
                    case HebrewAlphabet.Qof:
                        russianString.Append(RussianAlphabet.Ka);
                        break;
                    case HebrewAlphabet.Resh:
                        russianString.Append(RussianAlphabet.Re);
                        break;
                    case HebrewAlphabet.Shin:
//                        if (letter.ContainsShinDot)
//                        {
//                            special_O_should_be_Added = !prevLetter.isHasNiqqud() && !isFirstLetterInWord;
//                            if (special_O_should_be_Added)
//                            {
//                                russianString.Append(RussianAlphabet.O);
//                            }
//                        }
                        if (!isFirstLetterInWord && 
                            !prevLetter.isHasPureNiqqud() && 
                            !(prevLetter.Letter == HebrewAlphabet.Vav && prevLetter.isHasNiqqud()) &&
                            (prevLetter.Letter != HebrewAlphabet.Alef) && 
                            (prevLetter.Letter != HebrewAlphabet.Yod)
                            )
                        {
                            russianString.Append(RussianAlphabet.O);                            
                        }
                        if (letter.ContainsShinDot && letter.ContainsSinDot)
                        {
                            russianString.Append(RussianAlphabet.Sha);
                        }
                        else
                        {
                            russianString.Append(letter.ContainsSinDot ? RussianAlphabet.Se : RussianAlphabet.Sha);
                        }
                        break;
                    case HebrewAlphabet.Tav:
                        russianString.Append(RussianAlphabet.Te);
                        break;
                    #endregion
                }

                #region Rule 5
                if (letter.Letter == HebrewAlphabet.Vav)
                {
                    if (letter.ContainsLowNiqqud())
                    {
                        russianString.Append(RussianAlphabet.Ve);
                    }
                    else
                    {
                        if (letter.ContainsShuruk)
                        {
                            russianString.Append(!prevLetter.isHasPureNiqqud() ? RussianAlphabet.U : RussianAlphabet.Ve);
                        }
                        else if (letter.ContainsHolam)
                        {
                            if (prevLetter.isHasPureNiqqud())
                                russianString.Append(RussianAlphabet.Ve);
                            // 'o' wii be inserted by "Holam"
                            //russianString.Append(RussianAlphabet.O);
                        }
                        else
                            russianString.Append(RussianAlphabet.Ve);
                    }
                }
                #endregion

                #region Rule 7
                if (letter.Letter == HebrewAlphabet.Yod)
                {
                    bool isNotDagesh = !letter.ContainsDagesh;
                    bool isNextNiqud = letter.isHasNiqqud();
                    if (isLastLetterInWord)
                    {
                        bool silent = prevLetter.ContainsHiriq;

                        bool isIsShort = !silent;
                        if (isIsShort)
                            russianString.Append(RussianAlphabet.Ishort);
                    }
                    else
                    {
                        bool isNextShva = letter.ContainsShva;
                        bool isVavWithHolemOrShuruk = (nextLetter.Letter == HebrewAlphabet.Vav && (nextLetter.ContainsHolam || nextLetter.ContainsShuruk));
                        bool silent =
                            isNotDagesh
                            && !(isNextShva || isNextNiqud)
                            && (prevLetter.ContainsHiriq || prevLetter.ContainsSegol || prevLetter.ContainsZeire)
                            && (!isVavWithHolemOrShuruk);

                        bool isIsShort = !silent;

                        if (isIsShort)
                            russianString.Append(RussianAlphabet.Ishort);
                    }
                }
                #endregion

                #region Rule 6
                if (letter.ContainsShva)
                {
                    if (isLastLetterInWord)
                        continue;
                    if (prevLetter.ContainsHiriq)
                        continue;

                    if (isFirstLetterInWord)
                    {
                        russianString.Append(RussianAlphabet.Ie);
                    }
                    else
                    {
                        if (letter.ContainsDagesh)
                        {
                            russianString.Append(RussianAlphabet.Ie);
                            continue;
                        }

                        if (prevLetter.ContainsShuruk
                                || prevLetter.ContainsShva
                                || prevLetter.ContainsKamatz
                                || prevLetter.ContainsZeire
                                || prevLetter.ContainsHolam)
                        {
                            russianString.Append(RussianAlphabet.Ie);
                            continue;
                        }

                        if (letter.ContainsHiriq)
                        {
                            russianString.Append(RussianAlphabet.Ie);
                            continue;
                        }
                        if (letter.Letter == nextLetter.Letter)
                        {
                            russianString.Append(RussianAlphabet.Ie);
                            continue;
                        }
                        if (prevLetter.Letter == HebrewAlphabet.He && (prevLetter.ContainsKamatz || prevLetter.ContainsPatach))
                        {
                            russianString.Append(RussianAlphabet.Ie);
                            continue;
                        }
                        if (special_O_should_be_Added)
                        {
                            russianString.Append(RussianAlphabet.Ie);
                            continue;
                        }
                        else // "not Ie" ==> Rule 9
                        {
                            if (nextLetter.Letter == HebrewAlphabet.Ayin
                                || nextLetter.Letter == HebrewAlphabet.He
                                || nextLetter.Letter == HebrewAlphabet.Alef
                                || (nextLetter.Letter == HebrewAlphabet.Yod && nextLetter.isHasNiqqud()))
                            {
                                russianString.Append("'");
                            }
                        }
                    }
                }
                #endregion

                #region Rule 4
                if (letter.ContainsPatach)
                {
                    if (isLastLetterInWord && (letter.Letter == HebrewAlphabet.Het))
                    {
                        russianString.Insert(russianString.Length - 1, RussianAlphabet.A);
                    }
                    else
                    {
                        russianString.Append(RussianAlphabet.A);
                    }
                }
                if (letter.ContainsKamatz)
                    russianString.Append(RussianAlphabet.A);
                if (letter.ContainsZeire)
                    russianString.Append(RussianAlphabet.E);
                if (letter.ContainsSegol)
                    russianString.Append(RussianAlphabet.E);
                if (letter.ContainsHiriq)
                    russianString.Append(RussianAlphabet.I);
                if (letter.ContainsKubutz)
                    russianString.Append(RussianAlphabet.U);
                if (letter.ContainsHolam)
                    russianString.Append(RussianAlphabet.O);
                if (letter.ContainsHatavKamatz)
                    russianString.Append(RussianAlphabet.O);
                if (letter.ContainsHatavPatah)
                    russianString.Append(RussianAlphabet.A);
                if (letter.ContainsHatavSegol)
                    russianString.Append(RussianAlphabet.E);
                #endregion
            }

            return russianString.ToString();

            SimpleHebrewWord simpleHebrewWord = new SimpleHebrewWord();
            special_O_should_be_Added = false;

            russianString = new StringBuilder();
            for (int i = 0; i < hebrewWordText.Length; i++)
            {
                int actualIndex = i + preFix.Length;

                char nextChar = line[actualIndex + 1];
                bool lastLetterInWord = !HebrewWord.isHebrewLetter(nextChar, true);
                bool isNextShuruk = nextChar == HebrewNiqqud.Shuruk;
                bool isNextHolam = nextChar == HebrewNiqqud.Holam;
                bool isNextHiriq = nextChar == HebrewNiqqud.Hiriq;
                bool isNextSinDot = nextChar == HebrewNiqqud.SinDot;
                bool isNextShinDot = nextChar == HebrewNiqqud.ShinDot;
                bool isNextSegol = nextChar == HebrewNiqqud.Segol;
                bool isNextZeire = nextChar == HebrewNiqqud.Zeire;
                bool isPrevShuruk = (simpleHebrewWord.IsPrevActual && simpleHebrewWord.PrevLetter.ContainsShuruk) || (line[actualIndex - 1] == HebrewNiqqud.Shuruk);
                bool isPrevHiriq = (simpleHebrewWord.IsPrevActual && simpleHebrewWord.PrevLetter.ContainsHiriq) || (line[actualIndex - 1] == HebrewNiqqud.Hiriq);
                bool isPrevSegol = (simpleHebrewWord.IsPrevActual && simpleHebrewWord.PrevLetter.ContainsSegol) || (line[actualIndex - 1] == HebrewNiqqud.Segol);
                bool isPrevZeire = (simpleHebrewWord.IsPrevActual && simpleHebrewWord.PrevLetter.ContainsZeire) || (line[actualIndex - 1] == HebrewNiqqud.Zeire);
                bool isPrevPatach = (simpleHebrewWord.IsPrevActual && simpleHebrewWord.PrevLetter.ContainsPatach) || (line[actualIndex - 1] == HebrewNiqqud.Patach);
                bool isPrevKamatz = (simpleHebrewWord.IsPrevActual && simpleHebrewWord.PrevLetter.ContainsKamatz) || (line[actualIndex - 1] == HebrewNiqqud.Kamatz);

                char hebrewLetter = line[actualIndex];
                switch (hebrewLetter)
                {
                    #region Rule 2
                    case HebrewAlphabet.Bet:
                        russianString.Append(isNextShuruk ? RussianAlphabet.Be : RussianAlphabet.Ve);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.BetWithDagesh:
                        russianString.Append(RussianAlphabet.Be);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Gimel:
                        russianString.Append(RussianAlphabet.Ge);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Dalet:
                        russianString.Append(RussianAlphabet.De);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Zayin:
                        russianString.Append(RussianAlphabet.Ze);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Het:
                        russianString.Append(RussianAlphabet.Xa);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Tet:
                        russianString.Append(RussianAlphabet.Te);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Kaf:
                    case HebrewAlphabet.FinalKaf:
                        russianString.Append(isNextShuruk ? RussianAlphabet.Ka : RussianAlphabet.Xa);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.KafWithDagesh:
                        russianString.Append(RussianAlphabet.Ka);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Lamed:
                        russianString.Append(RussianAlphabet.L);
                        if (lastLetterInWord)
                            russianString.Append(RussianAlphabet.SoftSign);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Mem:
                    case HebrewAlphabet.FinalMem:
                        russianString.Append(RussianAlphabet.M);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Nun:
                    case HebrewAlphabet.FinalNun:
                        russianString.Append(RussianAlphabet.N);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Samekh:
                        russianString.Append(RussianAlphabet.Se);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Pe:
                    case HebrewAlphabet.FinalPe:
                        russianString.Append(isNextShuruk ? RussianAlphabet.Pe : RussianAlphabet.Fe);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.PeWithDagesh:
                        russianString.Append(RussianAlphabet.Pe);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Tsadi:
                    case HebrewAlphabet.FinalTsadi:
                        russianString.Append(RussianAlphabet.Tse);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Qof:
                        russianString.Append(RussianAlphabet.Ka);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Resh:
                        russianString.Append(RussianAlphabet.Re);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Shin:
                        if (isNextShinDot)
                        {
                            bool isPrevNiqud = isNiqqud(line[actualIndex - 1]) || (line[actualIndex - 1] == HebrewNiqqud.Shuruk);
                            special_O_should_be_Added = !isPrevNiqud && line[actualIndex - 1] != ' ';
                            if (special_O_should_be_Added)
                            {
                                russianString.Append(RussianAlphabet.O);
                            }
                        }
                        russianString.Append(isNextSinDot ? RussianAlphabet.Se : RussianAlphabet.Sha);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    case HebrewAlphabet.Tav:
                        russianString.Append(RussianAlphabet.Te);
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    #endregion

                    #region Rule 3
                    case HebrewAlphabet.Alef:
                    case HebrewAlphabet.He:
                    case HebrewAlphabet.Ayin:
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    #endregion

                    #region Rule 4
                    case HebrewNiqqud.Patach:
                        simpleHebrewWord.AddPatach();
                        if (lastLetterInWord && (line[actualIndex - 1] == HebrewAlphabet.Het))
                        {
                            russianString.Insert(russianString.Length - 1, RussianAlphabet.A);
                        }
                        else
                        {
                            russianString.Append(RussianAlphabet.A);
                        }
                        break;
                    case HebrewNiqqud.Kamatz:
                        simpleHebrewWord.AddKamatz();
                        russianString.Append(RussianAlphabet.A);
                        break;
                    case HebrewNiqqud.Zeire:
                        simpleHebrewWord.AddZeire();
                        russianString.Append(RussianAlphabet.E);
                        break;
                    case HebrewNiqqud.Segol:
                        simpleHebrewWord.AddSegol();
                        russianString.Append(RussianAlphabet.E);
                        break;
                    case HebrewNiqqud.Hiriq:
                        simpleHebrewWord.AddHiriq();
                        russianString.Append(RussianAlphabet.I);
                        break;
                    case HebrewNiqqud.Kubutz:
                        russianString.Append(RussianAlphabet.U);
                        break;
                    case HebrewNiqqud.Holam:
                        simpleHebrewWord.AddHolam();
                        russianString.Append(RussianAlphabet.O);
                        break;
                    #endregion

                    #region Rule 5
                    case HebrewAlphabet.Vav:
                        if (isNiqqudLow(line[actualIndex - 1]))
                        {
                            russianString.Append(RussianAlphabet.Ve);
                        }
                        else
                        {
                            if (isNextShuruk)
                                russianString.Append(RussianAlphabet.U);
                            else if (isNextHolam)
                            {
                                // 'o' wii be inserted by "Holam"
                                //russianString.Append(RussianAlphabet.O);
                            }
                            else
                                russianString.Append(RussianAlphabet.Ve);
                        }
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    #endregion

                    #region Rule 6
                    case HebrewNiqqud.Shva:
                        simpleHebrewWord.AddShva();

                        if (lastLetterInWord)
                            break;

                        #region Rule 6.1
                        if (simpleHebrewWord.LetterIndexInWord == 1)
                            russianString.Append(RussianAlphabet.Ie);
                        #endregion
                        else
                        {
                            #region Rule 6.1
                            if (simpleHebrewWord.LetterIndexInWord != 1)
                            {
                                bool prevLetterWithShuruk = (simpleHebrewWord.LetterIndexInWord != 2 && simpleHebrewWord.PrevLetter.ContainsShuruk) || (isPrevShuruk);
                                if (prevLetterWithShuruk
                                    || simpleHebrewWord.PrevLetter.ContainsShva
                                    || simpleHebrewWord.PrevLetter.ContainsKamatz
                                    || simpleHebrewWord.PrevLetter.ContainsZeire
                                    || simpleHebrewWord.PrevLetter.ContainsHolam)
                                {
                                    russianString.Append(RussianAlphabet.Ie);
                                    break;
                                }
                            }
                            if (simpleHebrewWord.TheLetter.ContainsHiriq)
                            {
                                russianString.Append(RussianAlphabet.Ie);
                                break;
                            }
                            if (simpleHebrewWord.TheLetter.Letter == nextChar)
                            {
                                russianString.Append(RussianAlphabet.Ie);
                                break;
                            }
                            if (simpleHebrewWord.LetterIndexInWord == 2
                                && simpleHebrewWord.PrevLetter.Letter == HebrewAlphabet.He
                                && (simpleHebrewWord.PrevLetter.ContainsKamatz || simpleHebrewWord.PrevLetter.ContainsPatach)
                                )
                            {
                                russianString.Append(RussianAlphabet.Ie);
                                break;
                            }
                            if (special_O_should_be_Added)
                            {
                                russianString.Append(RussianAlphabet.Ie);
                                break;
                            }
                            else // "not Ie" ==> Rule 9
                            {
                                if (nextChar == HebrewAlphabet.Ayin
                                    || nextChar == HebrewAlphabet.He
                                    || nextChar == HebrewAlphabet.Alef
                                    || (nextChar == HebrewAlphabet.Yod && line.Length > actualIndex + 2 && isNiqqud(line[actualIndex + 2])))
                                {
                                    russianString.Append("'");
                                }
                            }
                            #endregion
                        }
                        break;
                    #endregion

                    #region Rule 7
                    case HebrewAlphabet.Yod:
                        bool isNotDagesh = HebrewNiqqud.Dagesh != line[actualIndex + 1];
                        bool isNextNiqud = isNiqqud(line[actualIndex + 1]);
                        if (lastLetterInWord)
                        {
                            //bool silent = isNotDagesh && !isNextNiqud && !(isPrevPatach || isPrevKamatz);
                            bool silent = isPrevHiriq;

                            bool isIsShort = !silent;
                            if (isIsShort)
                                russianString.Append(RussianAlphabet.Ishort);
                        }
                        else
                        {
                            bool isNextShva = (HebrewNiqqud.Shva == line[actualIndex + 1]);
                            bool isVavWithHolemOrShuruk = (HebrewAlphabet.Vav == line[actualIndex + 1] && (HebrewNiqqud.Holam == line[actualIndex + 2] || HebrewNiqqud.Shuruk == line[actualIndex + 2]));
                            bool silent =
                                isNotDagesh
                                && !(isNextShva || isNextNiqud)
                                && (isPrevHiriq || isPrevSegol || isPrevZeire)
                                && (!isVavWithHolemOrShuruk);

                            bool isIsShort = !silent;

                            if (isIsShort)
                                russianString.Append(RussianAlphabet.Ishort);
                        }
                        simpleHebrewWord.AddLetter(hebrewLetter);
                        break;
                    #endregion

                    case HebrewNiqqud.Shuruk:
                        simpleHebrewWord.AddShuruk();
                        break;
                    case HebrewNiqqud.HatavKamatz:
                        russianString.Append(RussianAlphabet.O);
                        break;
                    case HebrewNiqqud.HatavPatah:
                        russianString.Append(RussianAlphabet.A);
                        break;
                    case HebrewNiqqud.HatavSegol:
                        russianString.Append(RussianAlphabet.E);
                        break;
                    case HebrewNiqqud.SinDot:
                        break;
                    case HebrewNiqqud.ShinDot:
                        break;
                    default:
                        #region Rule 1
                        russianString.Append(hebrewWordText[i]);
                        if (hebrewWordText[i] == ' ')
                        {
                            simpleHebrewWord.Clear();
                        }
                        #endregion
                        break;
                }
            }
            return russianString.ToString();
        }
        public bool isNiqqud(char hebrewChar)
        {
            return HebrewNiqqud.Shva == hebrewChar
                   || HebrewNiqqud.HatavSegol == hebrewChar
                   || HebrewNiqqud.HatavPatah == hebrewChar
                   || HebrewNiqqud.HatavKamatz == hebrewChar
                   || HebrewNiqqud.Hiriq == hebrewChar
                   || HebrewNiqqud.Zeire == hebrewChar
                   || HebrewNiqqud.Patach == hebrewChar
                   || HebrewNiqqud.Kamatz == hebrewChar
                   || HebrewNiqqud.SinDot == hebrewChar
                   || HebrewNiqqud.ShinDot == hebrewChar
                //                   || HebrewNiqqud.Shuruk == hebrewChar
                   || HebrewNiqqud.Kamatz == hebrewChar
                   || HebrewNiqqud.Kamatz == hebrewChar;
        }
        public bool isNiqqudLow(char hebrewChar)
        {
            return HebrewNiqqud.Shva == hebrewChar
                   || HebrewNiqqud.HatavSegol == hebrewChar
                   || HebrewNiqqud.HatavPatah == hebrewChar
                   || HebrewNiqqud.HatavKamatz == hebrewChar
                   || HebrewNiqqud.Hiriq == hebrewChar
                   || HebrewNiqqud.Zeire == hebrewChar
                   || HebrewNiqqud.Patach == hebrewChar
                   || HebrewNiqqud.Kamatz == hebrewChar;
            //|| HebrewNiqqud.SinDot == hebrewChar
            //|| HebrewNiqqud.ShinDot == hebrewChar
            //                   || HebrewNiqqud.Shuruk == hebrewChar
        }

        static char RussianToUp(char russian)
        {
            return char.ToUpper(russian);
        }
        void AddWordToResult(StringBuilder result, StringBuilder currentWord, IStatement statement)
        {
            //result.Append(ConvertWord(currentWord.ToString()));
            string nextRussianWord = ConvertWord(currentWord.ToString());
            if (statement.ConvertToUp)
            {
                nextRussianWord = RussianToUp(nextRussianWord[0]) + nextRussianWord.Substring(1, nextRussianWord.Length - 1);
            }

            if (postProcessing.Contains(nextRussianWord))
                nextRussianWord = RussianToUp(nextRussianWord[0]) + nextRussianWord.Substring(1, nextRussianWord.Length - 1);

            result.Append(nextRussianWord);
        }

        const string Name_russian = "А-доной";
        readonly IDictionary<string, string> specialWords = new Dictionary<string, string>
                                                               {
                                                                   {HebrewSpecial.NameOfG_d, Name_russian},
                                                                   {HebrewSpecial.NameOfG_d_2Yod, Name_russian},
                                                                   {HebrewSpecial.NameOfG_d_WithNiqqud, Name_russian},
                                                                   {HebrewSpecial.KOL, "коль"}
                                                               };

        readonly List<string> postProcessing = new List<string>
                                                           {
                                                               "йисраэль", 
                                                               "авраам",
                                                               "йицхак",
                                                               "яаков"
                                                           };
    }
    public class HebrewWord
    {
        readonly IList<HebrewLetter> asList = new List<HebrewLetter>();
        readonly string wordAsString;
        public IList<HebrewLetter> AsList { get { return asList; } }
        public HebrewWord(string wordAsString)
        {
            this.wordAsString = wordAsString;
            ConvertStringToList();
        }
        void ConvertStringToList()
        {
            asList.Clear();
            List<char> preNiqqudList = new List<char>();

            HebrewLetter currentLetter = null;
            for (int i = 0; i < wordAsString.Length; i++)
            {
                char currentChar = wordAsString[i];
                bool isLetter = isHebrewLetter(currentChar, false);
                if (isLetter)
                {
                    currentLetter = new HebrewLetter(currentChar);
                    if (preNiqqudList.Count > 0)
                    {
                        foreach (char niqqud in preNiqqudList)
                        {
                            currentLetter.AddNiqqud(niqqud);
                        }
                        preNiqqudList.Clear();
                    }
                    asList.Add(currentLetter);
                }
                else
                {
                    if (currentLetter != null)
                        currentLetter.AddNiqqud(currentChar);
                    else
                        preNiqqudList.Add(currentChar);
                }
            }
        }
        static public bool isHebrewLetter(char symbol, bool includeNiqqud)
        {
            // http://www.webtoolhub.com/tn561380-xhtml-characters-list.aspx?type=script&category=hebrew
            if (includeNiqqud)
                return (symbol >= '\u0591' && symbol <= '\u05F4');
            return (symbol >= '\u05D0' && symbol <= '\u05EA');

            //            if (isNiqqud(symbol))
            //                return true;
            //            if (symbol == HebrewNiqqud.Shuruk)
            //                return true;
            //            if (symbol >= HebrewAlphabet.Alef && symbol <= HebrewAlphabet.Tav)
            //                return true;
            //            return false;
        }
        static public bool isNiqqudLow(char hebrewChar)
        {
            return HebrewNiqqud.Shva == hebrewChar
                   || HebrewNiqqud.HatavSegol == hebrewChar
                   || HebrewNiqqud.HatavPatah == hebrewChar
                   || HebrewNiqqud.HatavKamatz == hebrewChar
                   || HebrewNiqqud.Hiriq == hebrewChar
                   || HebrewNiqqud.Zeire == hebrewChar
                   || HebrewNiqqud.Patach == hebrewChar
                   || HebrewNiqqud.Kamatz == hebrewChar;
            //|| HebrewNiqqud.SinDot == hebrewChar
            //|| HebrewNiqqud.ShinDot == hebrewChar
            //                   || HebrewNiqqud.Shuruk == hebrewChar
        }
    }
}
